package edu.lambdateacher.expressions;

/*
 LambdaTeacher
 Copyright (C) 2000  Kim Mason
 Copyright (C) 2014  Vitalij Zadneprovskij

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */


/**
 * The class HalfApplNumOp represents a Numerical Operator after it has been
 * applied to one argument. It is a subclass of Expression. It is of the form
 * <NumericalOperator> <arg>, where arg is a natural number. A HalfApplNumOp is
 * not reducable.
 */
public class HalfApplNumOp extends Expression implements Cloneable {
	// the numerical operator itself
	private NumericalOperator numericalOperator;
	// the argument of the applied numerical operator
	private Numbers argument;

	/**
	 * A simple constructor function
	 */
	public HalfApplNumOp() {
		super(); // this is implicit, but it can't hurt.
		this.setArgument(new Numbers(0));
		this.setNumericalOperator(new NumericalOperator());
	}

	public HalfApplNumOp(NumericalOperator inop, Numbers innum) {
		super();
		this.setArgument(innum);
		this.setNumericalOperator(inop);
	}

	public void setArgument(Numbers argset) {
		this.argument = argset;
	}

	public Numbers getArgument() {
		return this.argument;
	}

	public void setNumericalOperator(NumericalOperator inop) {
		this.numericalOperator = inop;
	}

	public NumericalOperator getNumericalOperator() {
		return this.numericalOperator;
	}

	/**
	 * Override the clone method in superclass Object. Simply clones the
	 * superclass, and sets the arg.
	 */
	public Object clone() {
		HalfApplNumOp toreturn = (HalfApplNumOp) super.clone();
		toreturn.setArgument((Numbers) this.getArgument().clone());
		toreturn.setNumericalOperator((NumericalOperator) this.getNumericalOperator().clone());
		return toreturn;
	}

	/**
	 * unParse returns a string which represents this expression verbose says
	 * whether to produce all brackets
	 */
	public String stringRepresentation(boolean verbose) {
		String toreturn = "";
		toreturn += getNumericalOperator().stringRepresentation(verbose) + " " + getArgument().stringRepresentation(verbose);
		return toreturn;
	}

	public Expression betaReduce(Application application){
		boolean involvehalfapp = true;
		NumericalOperator tempop = this.getNumericalOperator();
		NumericalOperatorType optype = tempop.getType();
		Numbers firstarg = this.getArgument();
		Numbers secondarg = (Numbers) application.getArgSkipBindings();
		int firstargval = firstarg.getValue();
		int secondargval = secondarg.getValue();

		int newvalue = 0;

		switch (optype) {
		case PLUS:
			newvalue = firstargval + secondargval;
			break;
		case MINUS:
			newvalue = firstargval - secondargval;
			break;
		case MULT:
			newvalue = firstargval * secondargval;
			break;
		case DIV:
			newvalue = firstargval / secondargval;
			break;
		default:
			break;
		}
		Expression toreturn = new Numbers(newvalue);
		return toreturn;
	}
	
}